#include "head.h"

// 数据操作
#include "head.h"

// 数据操作
//  向文件写入航班信息
void flight_data_file_print(f_list *list)
{
    // 安全判断
    if (NULL == list)  //判NULL
    {
        ERRLOG("双向循环链表 为 NULL");
        return;
    }
    if (NULL == list->next)  //判断链表里面是否有值
    {
        ERRLOG("双向循环链表 为 NULL");
        return;
    }

    FILE *fp = fopen(FLIGHTS_FILE, "w+");//以只读文件打开文件
    if (NULL == fp)//判断文件是否打开
    {
        ERRLOG("文件打开失败");
        return;
    }
    fseek(fp, 0, SEEK_SET);//移到行首
    f_node *ptr = list->next;//ptr移动到头指针的下一个节点
    do
    {
        fprintf(fp, "%d\t", ptr->data.id);
        fprintf(fp, "%s\t", ptr->data.flighttype);
        fprintf(fp, "%s\t", ptr->data.startcity);
        fprintf(fp, "%s\t", ptr->data.arrivecity);
        fprintf(fp, "%d:%d\t", ptr->data.starttime[0], ptr->data.starttime[1]);
        fprintf(fp, "%d:%d\t", ptr->data.arrivetime[0], ptr->data.arrivetime[1]);
        fprintf(fp, "%s\t", ptr->data.flytime);
        fprintf(fp, "%d\t", ptr->data.value);
        fprintf(fp, "%d\t", ptr->data.maxNUM);
        fprintf(fp, "%d\t", ptr->data.leftbuyersa);
        fprintf(fp, "%c\n", ptr->data.whetherfly);
         ptr = ptr->next;
    } while (ptr != list->next);//因为是循环链表，所以判断ptr的下一个节点是否到行首，如果是，就代表循环了一圈
    fclose(fp);//关闭文件
}
//  向文件读取航班信息
void flight_data_file_scanf(f_list *list)
{
    // 安全判断
    if (NULL == list)
    {
        ERRLOG("双向循环链表 为 NULL");
        return;
    }

    FILE *fp = fopen(FLIGHTS_FILE, "r+");//只读方式打开文件
    if (NULL == fp)//判NULL
    {
        ERRLOG("文件创建失败");
        return;
    }
    // 移动光标
    fseek(fp, 0, SEEK_SET);
    // 清空链表
    //clear_double_link_list(list);

    f_data data;
    char ch = 0;
    int pos = 0;

    // 检测文件行数
    while(EOF != (ch = fgetc(fp)))
    {
        if ('\n' ==  ch)
        {
            pos++;
        }
    }

    fflush(fp); // 刷新文件
    // 移动光标
    fseek(fp, 0, SEEK_SET);
    for (size_t i = 0; i < pos; i++)
    {//写入文件
        fscanf(fp, "%d\t", &data.id);
        fscanf(fp, "%s\t", data.flighttype);
        fscanf(fp, "%s\t", data.startcity);
        fscanf(fp, "%s\t", data.arrivecity);
        fscanf(fp, "%d:%d\t", &data.starttime[0], &data.starttime[1]);
        fscanf(fp, "%d:%d\t", &data.arrivetime[0], &data.arrivetime[1]);
        fscanf(fp, "%s\t", data.flytime);
        fscanf(fp, "%d\t", &data.value);
        fscanf(fp, "%d\t", &data.maxNUM);
        fscanf(fp, "%d\t", &data.leftbuyersa);
        fscanf(fp, "%c\n", &data.whetherfly);
        insert_double_node(list, data, i+1); //写入行数
    }
    fflush(fp); // 刷新文件
    fclose(fp);//关闭文件
}
// 双向链表的创建
f_list *init_double_link_list()
{
    // 1、创建动态空间
    f_list *list = (f_list *)malloc(sizeof(f_list));
    if (NULL == list)
    {
        ERRLOG("创建动态空间失败");
        return NULL;
    }
    // 2、初始化赋值
    list->next = NULL;
    list->len = 0;
    // 3、返回list
    return list;
}
// 双向链表的插入
void insert_double_node(f_list *list, f_data data, int pos)
{
    // 安全判断
    if (NULL == list)
    {
        ERRLOG("双向循环链表 为 NULL");
        return;
    }

    // 创建数据结点
    f_node *new_node = (f_node *)malloc(sizeof(f_node));
    if (NULL == new_node)
    {
        ERRLOG("创建动态空间失败");
        return;
    }
    // 结点初始化
    new_node->data = data;
    new_node->next = new_node;
    new_node->prev = new_node;

    // 头插
    if (1 == pos || NULL == list->next)
    {
        // 内部有数据的头插
        if (1 == pos && NULL != list->next)
        {
            // 1 指向 第一个结点
            f_node *ptr = list->next;
            // 2 将 pre 的 prev 的 next 指向 新结点
            ptr->prev->next = new_node;
            // 3 new_node 的 next 指向 ptr
            new_node->next = ptr;
            // 4 new_node 的 prev 指向 ptr 的 prev
            new_node->prev = ptr->prev;
            // 5 ptr 的 prev 指向 new_node
            ptr->prev = new_node;
            // 6 头结点 指向 新结点
            list->next = new_node;
            list->len++;
            return;
        }
        // 内部无数据的头插    内部无数据 默认 头插
        if (NULL == list->next)
        {
            list->next = new_node;
            list->len++;
            return;
        }
    }

    // 中间插入

    f_node *ptr = list->next;

    for (size_t i = 1; i < pos - 1; i++)
    {
        ptr = ptr->next;
    }

    // 开始插入
    // 1、 新结点的 next 指向 ptr的next
    new_node->next = ptr->next;
    // 2、 ptr next prev 指向 新结点
    ptr->next->prev = new_node;
    // 3、 新结点 prev 指向 ptr
    new_node->prev = ptr;
    // 4、 ptr next 指向 new_node
    ptr->next = new_node;
    list->len++;
}
// 双向链表的删除
void delete_double_node(f_list *list, int pos)
{
    // 安全判断
    if (NULL == list)
    {
        ERRLOG("双向循环链表 为 NULL");
        return;
    }
    if (NULL == list->next)
    {
        ERRLOG("双向循环链表 为 NULL");
        return;
    }

    // 删除
    f_node *ptr_1 = list->next;
    f_node *ptr_2 = ptr_1->next;

    // 头删  情况 1、 pos == 1  2、只有一个元素  ptr_1->next == list->nexts
    if (1 == pos || ptr_1->next == list->next)
    {
        // 只有一个结点数据的时候
        if (ptr_1->next == list->next)
        {
            free(list->next);
            list->next = NULL;
            return;
        }
        // 多个结点数据删第一个
        if (1 == pos)
        {
            // 1、 将头结点 指向 第二个 结点
            list->next = ptr_2;
            // 2、 将 ptr2 指向 尾结点
            ptr_2->prev = ptr_1->prev;
            // 3、 将尾结点 的 指向 第二个结点
            ptr_1->prev->next = ptr_2;
            // 4、 释放 ptr 1
            free(ptr_1);
        }
    }
}
//遍历
void print_forward_double_link_list(f_list *list)
{
    if (list == NULL) 
    {
        fprintf(stderr, "双向循环链表 为 NULL\n");
        return;
    }
    if (list->next == NULL) 
    {
        fprintf(stderr, "双向循环链表 无 数据\n");
        return;
    }

    system("clear");

    printf( "班次    机型        起点站  终点站  起飞时间    到达时间    飞行时间    票价  载客量  剩余座位  是否飞\n");
    printf( "--------------------------------------------------------------------------------------------------\n");

    f_node *ptr = list->next;
    do 
    {
        printf("%-6d", ptr->data.id);
        printf("%-15s", ptr->data.flighttype);
        printf("%-10s", ptr->data.startcity);
        printf("%-10s", ptr->data.arrivecity);
        printf("%02d:%02d\t", ptr->data.starttime[0], ptr->data.starttime[1]);
        printf("%02d:%02d\t    ", ptr->data.arrivetime[0], ptr->data.arrivetime[1]);
        printf("%-10s\t", ptr->data.flytime);
        printf("%-6d", ptr->data.value);
        printf("%-8d", ptr->data.maxNUM);
        printf("%-8d  ", ptr->data.leftbuyersa);
        printf("%c\n", ptr->data.whetherfly);
        ptr = ptr->next;
    } while (ptr != list->next);

    
    char ch = ' ';

    while (10 != ch)
    {
        sleep(1); // 当前进程进入休眠态 S
        ch = getchar();
    }
    
}
// 双向链表的清空
void clear_double_link_list(f_list *list)
{
    if (NULL == list ) 
    {
        ERRLOG("双向循环链表 为 NULL\n");
        return;
    }
    if ( NULL == list->next) 
    {
        ERRLOG("双向循环链表 无 数据\n");
        return;
    }

    f_node * ptr_1 = list->next->prev;
    f_node * ptr_2 = list->next->prev->prev;

    // 释放结点
    for (size_t i = 0; list->next != ptr_1; i++)
    {
        free(ptr_1);
        ptr_1 = ptr_2;
        if (list->next != ptr_2)
        {
            ptr_2 = ptr_2->prev;
        }
    }
    free(ptr_1);
}
// 双向链表的销毁
void free_double_link_list(f_list ** list)
{
    if (NULL == (*list) ) 
    {
        ERRLOG("双向循环链表 为 NULL\n");
        return;
    }
    if ( NULL == (*list)->next) 
    {
        free(*list);
        *list = NULL;
        ERRLOG("双向循环链表 为 NULL\n");
        return;
    }

    f_node * ptr_1 = (*list)->next->prev;
    f_node * ptr_2 = (*list)->next->prev->prev;

    // 释放结点
    for (size_t i = 0; (*list)->next != ptr_1; i++)
    {
        free(ptr_1);
        ptr_1 = ptr_2;
        if ((*list)->next != ptr_2)
        {
            ptr_2 = ptr_2->prev;
        }
    }
    free(ptr_1);

    // 释放头结点
    free(*list);
    *list = NULL;
}